package com.google.code.chaotic.client;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.control.LargeMapControl;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.geocode.DirectionQueryOptions;
import com.google.gwt.maps.client.geocode.DirectionResults;
import com.google.gwt.maps.client.geocode.Directions;
import com.google.gwt.maps.client.geocode.DirectionsCallback;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LocationCallback;
import com.google.gwt.maps.client.geocode.Placemark;
import com.google.gwt.maps.client.geocode.StatusCodes;
import com.google.gwt.maps.client.geocode.Waypoint;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.Polyline;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Chaos extends com.google.gwt.user.client.ui.DecoratorPanel {

	// private static final Log LOG = LogFactory.getLog(Chaos.class);

	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Greeting
	 * service.
	 */
	private final JavaServiceAsync greetingService = GWT
			.create(JavaService.class);

	private MapWidget map;

	private Placemark startingPlace;
	private Placemark checkPlace;
	private Placemark endPlace;

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		Log.debug("ENTERING onModuleLoad()");

		// TODO: Must be changed to use a caching approach
		Geocoder geocoder = new Geocoder();

		geocoder.getLocations("Green Avenue, Bukit Jalil, Kuala Lumpur",
				new LocationCallback() {

					@Override
					public void onSuccess(JsArray<Placemark> locations) {
						init(locations.get(0));
					}

					@Override
					public void onFailure(int statusCode) {
						// TODO Auto-generated method stub

					}
				});

		geocoder.getLocations("MIMOS, Kuala Lumpur", new LocationCallback() {

			@Override
			public void onSuccess(JsArray<Placemark> locations) {
				endPlace = locations.get(0);
			}

			@Override
			public void onFailure(int statusCode) {
				// TODO Auto-generated method stub

			}
		});

		geocoder.getLocations("Vista Komanwel, Bukit Jalil, Kuala Lumpur",
				new LocationCallback() {

					@Override
					public void onSuccess(JsArray<Placemark> locations) {
						checkPlace = locations.get(0);
					}

					@Override
					public void onFailure(int statusCode) {
						// TODO Auto-generated method stub

					}
				});

		new Timer() {
			private long ms = System.currentTimeMillis();

			@Override
			public void run() {
				Log.debug("ENTERING Timer.run()");
				if (startingPlace == null || endPlace == null
						|| checkPlace == null) {

					if (System.currentTimeMillis() - ms < 10000)
						return;
					else
						cancel();
				}

				// DirectionsPanel dir = new DirectionsPanel();
				// RootPanel.get("directionsDiv").add(dir);

				DirectionQueryOptions directionOptions = new DirectionQueryOptions(
						map);

				// Directions.load(startingPlace.getPoint().toUrlValue() +
				// " to "
				// + endPlace.getPoint().toUrlValue(),
				// directionOptions,
				// new DirectionsCallback() {

				Directions.loadFromWaypoints(new Waypoint[] {
						new Waypoint(startingPlace), new Waypoint(checkPlace),
						new Waypoint(endPlace) }, directionOptions,
						new DirectionsCallback() {

							@Override
							public void onSuccess(DirectionResults result) {
								Log.debug("ENTERING onSuccess");

								Polyline line = result.getPolyline();
								// line.setEditingEnabled(PolyEditingOptions.newInstance(2,
								// true));

								// List<Route> routes = result.getRoutes();
								// for (Route r : routes) {
								// Placemark start = r.getStartGeocode();
								// Log.debug("start of route: " +
								// start.getAddress(),
								// null);
								// Placemark end = r.getEndGeocode();
								// Log.debug("end of route: " +
								// end.getAddress(),
								// null);
								// }

								// Route routes = result.getRoutes().get(0);
								// Placemark start = routes.getStartGeocode();
								// Placemark end = routes.getEndGeocode();

								Log.debug("EXITING onSuccess");
							}

							@Override
							public void onFailure(int statusCode) {
								GWT
										.log("INSIDE onFailure,"
												+ "STATUS: "
												+ StatusCodes
														.getName(statusCode),
												null);
							}
						});

				cancel();
				Log.debug("EXITING Timer.run()");
			}
		}.scheduleRepeating(250);

		/*
		 * final Button sendButton = new Button("Send"); final TextBox nameField
		 * = new TextBox(); nameField.setText("GWT User");
		 * 
		 * // We can add style names to widgets
		 * sendButton.addStyleName("sendButton");
		 * 
		 * // Add the nameField and sendButton to the RootPanel // Use
		 * RootPanel.get() to get the entire body element
		 * RootPanel.get("nameFieldContainer").add(nameField);
		 * RootPanel.get("sendButtonContainer").add(sendButton);
		 * 
		 * // Focus the cursor on the name field when the app loads
		 * nameField.setFocus(true); nameField.selectAll();
		 * 
		 * // Create the popup dialog box final DialogBox dialogBox = new
		 * DialogBox(); dialogBox.setText("Remote Procedure Call");
		 * dialogBox.setAnimationEnabled(true); final Button closeButton = new
		 * Button("Close"); // We can set the id of a widget by accessing its
		 * Element closeButton.getElement().setId("closeButton"); final Label
		 * textToServerLabel = new Label(); final HTML serverResponseLabel = new
		 * HTML(); VerticalPanel dialogVPanel = new VerticalPanel();
		 * dialogVPanel.addStyleName("dialogVPanel"); dialogVPanel.add(new
		 * HTML("<b>Sending name to the server:</b>"));
		 * dialogVPanel.add(textToServerLabel); dialogVPanel.add(new
		 * HTML("<br><b>Server replies:</b>"));
		 * dialogVPanel.add(serverResponseLabel);
		 * dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		 * dialogVPanel.add(closeButton); dialogBox.setWidget(dialogVPanel);
		 * 
		 * // Add a handler to close the DialogBox
		 * closeButton.addClickHandler(new ClickHandler() { public void
		 * onClick(ClickEvent event) { dialogBox.hide();
		 * sendButton.setEnabled(true); sendButton.setFocus(true); } });
		 * 
		 * // Create a handler for the sendButton and nameField class MyHandler
		 * implements ClickHandler, KeyUpHandler {
		 *//**
		 * Fired when the user clicks on the sendButton.
		 */
		/*
		 * public void onClick(ClickEvent event) { sendNameToServer(); }
		 *//**
		 * Fired when the user types in the nameField.
		 */
		/*
		 * public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode()
		 * == KeyCodes.KEY_ENTER) { sendNameToServer(); } }
		 *//**
		 * Send the name from the nameField to the server and wait for a
		 * response.
		 */
		/*
		 * private void sendNameToServer() { sendButton.setEnabled(false);
		 * String textToServer = nameField.getText();
		 * textToServerLabel.setText(textToServer);
		 * serverResponseLabel.setText("");
		 * greetingService.greetServer(textToServer, new AsyncCallback<String>()
		 * { public void onFailure(Throwable caught) { // Show the RPC error
		 * message to the user dialogBox
		 * .setText("Remote Procedure Call - Failure"); serverResponseLabel
		 * .addStyleName("serverResponseLabelError");
		 * serverResponseLabel.setHTML(SERVER_ERROR); dialogBox.center();
		 * closeButton.setFocus(true); }
		 * 
		 * public void onSuccess(String result) {
		 * dialogBox.setText("Remote Procedure Call"); serverResponseLabel
		 * .removeStyleName("serverResponseLabelError");
		 * serverResponseLabel.setHTML(result); dialogBox.center();
		 * closeButton.setFocus(true); } }); } }
		 * 
		 * // Add a handler to send the name to the server MyHandler handler =
		 * new MyHandler(); sendButton.addClickHandler(handler);
		 * nameField.addKeyUpHandler(handler);
		 */

		Log.debug("EXISTING onModuleLoad()");
	}

	private void init(Placemark placemark) {
		Log.debug("ENTERING init()");
		startingPlace = placemark;

		LatLng startingPoint = startingPlace.getPoint();
		map = new MapWidget(startingPoint, 12);
		map.setSize("100%", "400px");

		// Add some controls for the zoom level
		map.addControl(new LargeMapControl());

		// Add a marker
		final Marker marker = new Marker(startingPoint);
		map.addOverlay(marker);

		// Add an info window to highlight a point of interest
		// map.getInfoWindow().open(map.getCenter(),
		// new InfoWindowContent("World's Largest Ball of Sisal Twine"));

		marker.addMarkerClickHandler(new MarkerClickHandler() {
			@Override
			public void onClick(MarkerClickEvent event) {
				map.getInfoWindow().open(
						marker,
						new InfoWindowContent(
								"The result of \"Window.location\" invocation is:<br />"
										+ Window.Location.getHref()));
			}
		});

		// Add the map to the HTML host page
		// RootPanel.get("map").add(map);
		this.add(map);

		Log.debug("EXITING init()");
	}
}
